#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QMdiArea>
#include <QAction>
#include <QActionGroup>
#include <QToolBar>
#include <QTextEdit>
#include <QMenu>
#include <QLabel>
#include <QDockWidget>
#include <list>
#include <map>
#include <utility>
#include <string>
#include "src/core/mvc/controller.h"
#include "src/core/mvc/model.h"
#include "src/core/generic/translator.h"
#include "src/gui/qt/loggerwidget.h"
#include "src/gui/view.h"
#include "src/gui/qt/workspacewidget.h"
class WorkSpace;

class MainWindow : public QMainWindow, public View
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = 0);
  ~MainWindow();
  enum MenuType {ClassicalMenu, ProfessionalMenu};
  enum ToolBarFlag {General = 0x1, WindowControl = 0x2, Edit = 0x4};
  Q_DECLARE_FLAGS(ToolBarFlags, ToolBarFlag)
  enum WidgetFlag {LogWidget = 0x1};
  Q_DECLARE_FLAGS(WidgetFlags, WidgetFlag)
  enum SelectionBehaviourFlag {Append = 0x1, Replace = 0x2};
  Q_DECLARE_FLAGS(SelectionBehaviourFlags, SelectionBehaviourFlag)
  bool tabbedViewFlag;
  bool cascadeViewFlag;

  virtual void setController(Controller* contr) { controller = contr; }
private:
  void createWidgets();
  void createActions();
  void createClassicalMenu();
  void createProfessionalMenu();
  void setClassicalMenu();
  void setProfessionalMenu();
  void createStatusBar();
  void createToolbars();
  void loadSettings();
  void saveSettings();
private:
  typedef WorkspaceWidget ViewWidget;
  typedef std::map<int, ViewWidget*> widgetMap;

  widgetMap wspWidgets;

  Controller* controller;
  QMdiArea *mdiArea;
  QLabel *statusLabel;
  QToolBar *generalToolBar;
  QToolBar *editToolBar;
  QToolBar *windowControlToolBar;
  LoggerWidget *loggerWidget;
  QDockWidget *loggerWidgetDock;

  // classical menu tree
  QMenu *fileMenu;
    QMenu *fileNewMenu;
    QMenu *fileRecentMenu;
    QMenu *fileImportMenu;
    QMenu *fileExportMenu;
  QMenu *editMenu;
    QMenu *editInsertMenu;
    QMenu *editTransformMenu;
    QMenu *editStyleMenu;
  QMenu *selectionMenu;
    QMenu *selectionCriterialMenu;
    QMenu *selectionModeMenu;
  QMenu *toolsMenu;
    QMenu *toolsGenerateSurfaceMenu;
    QMenu *toolsGenerateFieldMenu;
      QMenu *toolsGenFieldLatticeMenu;
      QMenu *toolsGenFieldFieldMenu;
    QMenu *toolsInterpolateFieldMenu;
    QMenu *toolsCompareMenu;
    QMenu *toolsLoggingMenu;
  QMenu *viewMenu;
  QMenu *settingsMenu;
  QMenu *windowMenu;
    QMenu *windowAlignMenu;
  QMenu *helpMenu;

  QAction *newSessionAction;
  QAction *newDocumentAction;
  QAction *openAction;
  QAction *saveAction;
  QAction *saveAllAction;
  QAction *recentAction[5];
  QAction *importStructureAction;
  QAction *importLatticeAction;
  QAction *importFieldAction;
  QAction *importStyleAction;
  QAction *importSurfaceAction;
  QAction *exportStructureAction;
  QAction *exportLatticeAction;
  QAction *exportFieldAction;
  QAction *exportStyleAction;
  QAction *exportImageAction;
  QAction *exportSurfaceAction;
  QAction *closeAction;
  QAction *exitAction;
  QAction *redoAction;
  QAction *undoAction;
  QAction *removeAction;
  QAction *cutAction;
  QAction *copyAction;
  QAction *pasteAction;
  QAction *insertArrowAction;
  QAction *insertLineAction;
  QAction *insertLabelAction;
  QAction *insertTextAction;
  QAction *translateAction;
  QAction *rotateAction;
  QAction *scaleAction;
  QAction *setCpkAction;
  QAction *setBSAction;
  QAction *setWireframeAction;
  QAction *showAction;
  QAction *hideAction;
  QAction *selectAllAction;
  QAction *unselectAllAction;
  QAction *selectNearestAction;
  QAction *invertSelectionAction;
  QAction *selectionAppendAction;
  QAction *selectionReplaceAction;
  QActionGroup *selectionBehaviourActions;
  QAction *itemInspectorAction;\
  QAction *generateSurfaceConnolyAction;
  QAction *generateLatticeConnolyAction;
  QAction *generateFieldChargesAction;
  QAction *interpolateFieldLinearAction;
  QAction *interpolateFieldCubicSplinesAction;
  QAction *compareFieldsAction;
  QAction *compareStructuresSyncRotationAction;
  QAction *compareStructuresOneWindowAction;
  QAction *runScriptAction;
  QAction *loggingStartAction;
  QAction *loggingStopAction;
  QAction *loggingPauseAction;
  QAction *generateScriptAction;
  QAction *stopProcessAction;
  QAction *styleInspectorAction;
  QAction *viewGeneralToolBarAction;
  QAction *viewEditToolBarAction;
  QAction *viewWindowControlToolBarAction;
  QAction *viewLoggerWidgetAction;
  QAction *preferencesAction;
  QAction *classicalMenuAction;
  QAction *professionalMenuAction;
  QActionGroup *menuChangeRequestActions;
  QAction *minimizeAction;
  QActionGroup *subViewModeGroup;
  QAction *cascadeWindowsAction;
  QAction *tileWindowsAction;
  QActionGroup *viewModeGroup;
  QAction *subWindowViewAction;
  QAction *tabbedViewAction;
  QList<QAction *> openedWindowActions;
  QAction *applicationHelpAction;
  QAction *whatIsThisAction;
  QAction *aboutAction;

  QTextBrowser *helpBrowser;

  //some triggers
  MenuType menuType;
  SelectionBehaviourFlags selectionBehaviuorFlags;
  ToolBarFlags toolBarFlags;
  WidgetFlags widgetFlags;
private slots:
  //slots for actions
  void newSession();
  void newDocument()
  {
    controller->newDocument();
  }
  void saveDocument(int wspId)
  {
    controller->save(wspId);
  }
  void removeWorkspace(int wspId)
  {
    controller->close(wspId);
    wspWidgets.erase(wspId);
  }
  void setWspSaved(const int wspId, const bool saved = true);

  void open();
  void save();
  void saveAll();
  void recent();
  void importStructure();
  void importLattice();
  void importField();
  void importStyle();
  void importSurface();
  void exportStructure();
  void exportLattice();
  void exportField();
  void exportStyle();
  void exportSurface();
  void exportImage();
  void closeTab();
  void exit();
  void redo();
  void undo();
  void remove();
  void cut();
  void copy();
  void paste();
  void insertArrow();
  void insertLine();
  void insertLabel();
  void insertText();
  void translate();
  void rotate();
  void scale();
  void setCpk();
  void setBS();
  void setWireframe();
  void showItems(); // show() and hide() controls the window visibility
  void hideItems();
  void selectAll();
  void unselectAll();
  void selectNearest();
  void invertSelection();
  void selectionBehaviourChanged(QAction *action);
  void itemInspectorCall(); // itemInspector is convenient name for pointer to object
  void generateSurfaceConnoly();
  void generateLatticeConnoly();
  void generateFieldCharges();
  void interpolateFieldLinear();
  void interpolateFieldCubicSplines();
  void compareFields();
  void compareStructuresSyncRotation();
  void compareStructuresOneWindow();
  void runScript();
  void loggingStart();
  void loggingStop();
  void loggingPause();
  void generateScript();
  void stopProcess();
  void styleInspectorCall(); // styleInspector is convenient pointer name
  void viewGeneralToolBar();
  void viewEditToolBar();
  void viewWindowControlToolBar();
  void viewLoggerWidget();
  void viewLoggerWidget(bool state);
  void preferences();
  void menuChangeRequested(QAction*);
  void setViewMode(QAction*);
  void help();
  void whatIsThisRequested();
  void aboutVizMF();
public slots:
  void setStatusText(const std::string& text);
public:
  void createWidgetForWsp(int wspId, std::string name);
  void newLogEntry(const LoggerRecord& record);
  void warnUser(const Logger::container_type& container);
  ItemWidget* widgetForWsp(int wspId)
  {
    return (ItemWidget*) wspWidgets.at(wspId);
  }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(MainWindow::ToolBarFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(MainWindow::SelectionBehaviourFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(MainWindow::WidgetFlags)

#endif // MAINWINDOW_H
